package com.gack.business.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gack.business.model.ManagerUpdateLog;
import com.gack.business.model.Message;
import com.gack.business.model.Permission;
import com.gack.business.model.PermissionGroup;
import com.gack.business.model.PushSwitch;
import com.gack.business.model.UserEnterprisePermissionGroup;
import com.gack.business.permisson.exception.PermissionArrayIsNullException;
import com.gack.business.repository.EnterpriseRepository;
import com.gack.business.repository.ManagerUpdateLogRepository;
import com.gack.business.repository.MessageRepository;
import com.gack.business.repository.PermissionRepository;
import com.gack.business.repository.PushSwitchRepository;
import com.gack.business.repository.UserEnterpriseDepartmentPositionRepository;
import com.gack.business.repository.UserEnterprisePermissionGroupRepository;
import com.gack.business.repository.UserRepository;
import com.gack.business.vo.ManagerItemVO;
import com.gack.helper.common.util.JPushRestAPI;
import com.gack.helper.common.util.MapAsReturn;
import com.gack.helper.common.util.Pinyin;
import com.gack.helper.common.util.SendCode;
import com.gack.helper.modelUtils.DepartmentUtils;
import com.gack.helper.redis.RedisClient;

/**
 * 
 * @author ws
 * 2018-6-2
 */
@Service
@Transactional
public class ManagerService implements ManagerServiceInterface{

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private UserRepository userRepository;
	@Autowired
	private UserEnterprisePermissionGroupRepository userEnterprisePermissionGroupRepository;
	@Autowired
	private PermissionRepository permissionRepository;
	@Autowired
	private UserEnterpriseDepartmentPositionRepository userEnterpriseDepartmentPositionRepository;
	@Autowired
	private RedisClient jedis;
	@Autowired
	private MessageRepository messageRepository;
	@Autowired
	private PushSwitchRepository pushSwitchRepository;
	@Autowired
	private EnterpriseRepository enterpriseRepository;
	@Autowired
	private ManagerUpdateLogRepository managerUpdateLogRepository;
	@Autowired
	private DepartmentUtils departmentUtils;
	
	/**
	 * 查找公司的所有管理员(包含主管理员)
	 * @param enterpriseId 公司id
	 * @param userId 操作者id
	 * @return status:error/success  msg:错误或成功消息      managerList:管理员集合(不包含主管理员) superManager:主管理员
	 */
	@Override
	public Map<String, Object> findAllManager(String enterpriseId, String userId) {
		List<ManagerItemVO> manageList = new ArrayList<>();
		
		ManagerItemVO superManager = new ManagerItemVO();//主管理员
		
		//查询公司下所有管理员(此时包含主管理员)
		List<UserEnterprisePermissionGroup> uepgList = userEnterprisePermissionGroupRepository.findManager(enterpriseId);
		
		for(UserEnterprisePermissionGroup element : uepgList){
			
			ManagerItemVO manager = new ManagerItemVO();
			manager.setUserId(element.getUserId());
			List<Object[]> attributeArray = userRepository.findPortraitAndDepartmentIdAndPositionNameAndUsernameAndNameForShow(enterpriseId, element.getUserId(), userId);
			if(attributeArray == null || attributeArray.size() != 1 || attributeArray.get(0).length != 5){
				return MapAsReturn.setStatusError("非法用户查询");
			}
			manager.setPortrait((String)attributeArray.get(0)[0]);
			manager.setDepartmentName(departmentUtils.getDepartmentName((String)attributeArray.get(0)[1]));
			manager.setPositionName(StringUtils.isBlank((String)attributeArray.get(0)[2])?"无":(String)attributeArray.get(0)[2]);
			manager.setUsername((String)attributeArray.get(0)[3]);
			manager.setUserNameForShow((String)attributeArray.get(0)[4]);
			manager.setPermissionGroupList(PermissionGroup.parseToPermissionGroupList(element.getPermissionGroupsDescription()));
			
			if(element.getOpenDescription().contains("SUPER_PERMISSION")){
				superManager = manager;
			}else{
				manageList.add(manager);
			}
			
		}
		
		Comparator<ManagerItemVO> comparator = new Comparator<ManagerItemVO>(){
			@Override
			public int compare(ManagerItemVO m1, ManagerItemVO m2) {
				String s1 = Pinyin.getStringPinYin(m1.getUserNameForShow());
				String s2 = Pinyin.getStringPinYin(m2.getUserNameForShow());
				return s1.compareTo(s2);
			}
		};
		Collections.sort(manageList, comparator);
		
		Map<String, Object> map = MapAsReturn.setStatusSuccess("manageList", manageList);
		map.put("superManager", superManager);
		return map;
	}
	
	/**
	 * 删除管理员
	 * @param userId 用户id(idd1;id2;id3)
	 * @param enterpriseId 公司id
	 * @param operatorId 操作者id
	 * @return  status:error/success msg:错误或成功消息
	 */
	@Override
	public Map<String, Object> deleteManager(String userId, String enterpriseId, String operatorId) {
		
		for(String element : userId.split(";")){
			if(StringUtils.isBlank(element)){
				continue;
			}
			
			//获取旧权限组
			UserEnterprisePermissionGroup oldUepg = userEnterprisePermissionGroupRepository.findByUserIdAndEnterpriseId(element, enterpriseId);
			
			userEnterprisePermissionGroupRepository.deleteByUserIdAndEnterpriseId(element, enterpriseId);
			
			Date date = new Date();
			//告知用户权限变更(发送站内信、push)
			oldUepg = (oldUepg==null?new UserEnterprisePermissionGroup():oldUepg);
			String text = getTextAboutManagerUpdate(operatorId, element, enterpriseId, oldUepg, new UserEnterprisePermissionGroup());
			sendInMail(operatorId, element, text, date);//发送站内信
			sendPush(operatorId, userRepository.findUsernameById(element), text, date);//发送push
			
			//记录权限变更操作
			saveManagerUpdateLog(operatorId, element, enterpriseId, oldUepg, new UserEnterprisePermissionGroup(), date);
		}
		
		return MapAsReturn.setStatusSuccess(null, null);
	}

	/**
	 * 根据用户id、公司id查找权限组(若无权限组,则返回默认权限组)
	 * @param userId 用户id
	 * @param enterpriseId 公司id
	 * @return status:error/success msg:错误或成功消息  permissionGroupList:PermissionGroup集合
	 */
	@Override
	public Map<String, Object> findPermissionGroupList(String userId, String enterpriseId) {
		UserEnterprisePermissionGroup uepg = userEnterprisePermissionGroupRepository.findByUserIdAndEnterpriseId(userId, enterpriseId);
		if(uepg == null){
			uepg = userEnterprisePermissionGroupRepository.findByUserIdAndEnterpriseId("-1", "-1");
		}
		
		if(uepg.getOpenDescription().contains("SUPER_PERMISSION")){
			return MapAsReturn.setStatusError("非法查询");
		}
		
		//取出权限组
		List<PermissionGroup> permissionGroupList = PermissionGroup.parseToPermissionGroupList(uepg.getPermissionGroupsDescription());
		
		Comparator<PermissionGroup> comparator = new Comparator<PermissionGroup>(){
			@Override
			public int compare(PermissionGroup m1, PermissionGroup m2) {
				String s1 = Pinyin.getStringPinYin(m1.getTitle());
				String s2 = Pinyin.getStringPinYin(m2.getTitle());
				return -s1.compareTo(s2);
			}
		};
		Collections.sort(permissionGroupList, comparator);
		
		return MapAsReturn.setStatusSuccess("permissionGroupList", permissionGroupList);
	}
	
	/**
	 * 保存权限组
	 * @param userId 用户id
	 * @param enterpriseId 公司id
	 * @param permissionGroupList 权限组集合
	 * @param operatorId 操作者id
	 * @return status:error/success msg:错误或成功消息  managerList:管理员集合(包含主管理员)
	 */
	@Override
	public Map<String, Object> savePermissionGroup(String userId, String enterpriseId, List<PermissionGroup> permissionGroupList, String operatorId) {
		
		//判断新权限组是否符合open一致性
		for(PermissionGroup element : permissionGroupList){
			try {
				if(!element.verifyOpen()){
					return MapAsReturn.setStatusError("open属性不一致");
				}
			} catch (PermissionArrayIsNullException e) {
				return MapAsReturn.setStatusError(e.getMessage());
			}
		}
		
		//获取userId的旧权限
		UserEnterprisePermissionGroup oldUepg = userEnterprisePermissionGroupRepository.findByUserIdAndEnterpriseId(userId, enterpriseId);
		
		//删除用户权限组
		userEnterprisePermissionGroupRepository.deleteByUserIdAndEnterpriseId(userId, enterpriseId);
	
		Date date = new Date();
		//保存用户新权限组
		UserEnterprisePermissionGroup uepg = new UserEnterprisePermissionGroup();
		if(PermissionGroup.hasOpenPermissionGroup(permissionGroupList)){//判断权限组集合中是否有权限组为开启状态
			uepg.setUserId(userId);
			uepg.setEnterpriseId(enterpriseId);
			uepg.setPermissionGroupsDescription(PermissionGroup.parseToString(permissionGroupList));
			uepg.setManagerTime(date);
			uepg = userEnterprisePermissionGroupRepository.save(uepg);
		}
		
		//告知用户权限变更(发送站内信、push)
		oldUepg = (oldUepg==null?new UserEnterprisePermissionGroup():oldUepg);
		String text = getTextAboutManagerUpdate(operatorId, userId, enterpriseId, oldUepg, uepg);
		sendInMail(operatorId, userId, text, date);//发送站内信
		sendPush(operatorId, userRepository.findUsernameById(userId), text, date);//发送push
		
		//记录权限变更操作
		saveManagerUpdateLog(operatorId, userId, enterpriseId, oldUepg, uepg, date);
		
		return findAllManager(enterpriseId, operatorId);
	}

	/**
	 * 查找某人所具有的权限
	 * @param enterpriseId 公司id
	 * @param userId 用户id
	 * @return status:error/success msg:错误或成功消息   permissionList:Permission集合
	 */
	@Override
	public Map<String, Object> findPermissionByUserId(String enterpriseId, String userId){
		List<Permission> permissionList = new ArrayList<>();
		
		UserEnterprisePermissionGroup uepg = userEnterprisePermissionGroupRepository.findByUserIdAndEnterpriseId(userId, enterpriseId);
		if(null == uepg){
			return MapAsReturn.setStatusSuccess("permissionList", permissionList);
		}
		
		return MapAsReturn.setStatusSuccess("permissionList", uepg.getOpenPermission());
	}
	
	/**
	 * 查找公司超级管理员的手机号
	 * @param enterpriseId 公司id
	 * @return status:error/success msg:错误或成功消息  username:超级管理员手机号
	 */
	@Override
	public Map<String, Object> findSuperManagerUsername(String enterpriseId){
		List<UserEnterprisePermissionGroup> uepgList = userEnterprisePermissionGroupRepository.findManager(enterpriseId);
		
		String superManagerId = null;
		for(UserEnterprisePermissionGroup element : uepgList){
			if(element.getOpenDescription().contains("SUPER_PERMISSION")){
				superManagerId = element.getUserId();
			}
		}
		
		if(StringUtils.isBlank(superManagerId)){
			return MapAsReturn.setStatusError("查无超级管理员");
		}
		
		return MapAsReturn.setStatusSuccess("username", userRepository.findUsernameById(superManagerId));
	}
	
	/**
	 * 发送短信验证码,用来更换超级管理员
	 * @param enterpriseId 公司id
	 * @return status:error/success msg:错误或成功消息
	 */
	public Map<String, Object> sendCodeForSetSuperManager(String enterpriseId){
		Map<String, Object> map = findSuperManagerUsername(enterpriseId);
		if(map.get("status").equals("error")){
			return map;
		}
		
		String username = (String)map.get("username");
		StringBuilder sb = new StringBuilder();
		for(int i=0; i<4; i++){
			sb.append(new Random().nextInt(10));
		}

		jedis.setex(username + "ForSetSuperManager", 5 * 60, sb.toString());
	
		try{
			SendCode.sendMessage(username, "验证码是" + sb.toString() + ",您正在申请移交公司,验证码5分钟内有效,如非本人操作,请忽略本信息,切勿转发告知他人。");
		}catch(Exception e){
			logger.error("发送移交公司验证码异常。enterpriseId=" + enterpriseId);
		}
		
		return MapAsReturn.setStatusSuccess(null, null);
	}
	
	/**
	 * 更换超级管理员
	 * @param operatorId 操作者id
	 * @param enterpriseId 公司id
	 * @param userId 用户id
	 * @param code 验证码
	 * @return status:error/success msg:错误或成功消息
	 */
	@Override
	public Map<String, Object> setSuperManager(String operatorId, String enterpriseId, String userId, String code){
		//判断被操作者是否在公司内
		if(userEnterpriseDepartmentPositionRepository.countByUserIdAndEnterpriseId(userId, enterpriseId) == 0){
			return MapAsReturn.setStatusError("非法操作");
		}
		
		//判断验证码是否正确
		Map<String, Object> map = findSuperManagerUsername(enterpriseId);
		if(map.get("status").equals("error")){
			return map;
		}
		String codeStored = jedis.get(map.get("username") + "ForSetSuperManager");
		if(StringUtils.isBlank(codeStored)){
			return MapAsReturn.setStatusError("验证码失效,请重新获取");
		}
		if(!code.equals(codeStored)){
			return MapAsReturn.setStatusError("验证码有误,请重新输入");
		}
		
		//删除操作者管理员权限
		userEnterprisePermissionGroupRepository.deleteByUserIdAndEnterpriseId(operatorId, enterpriseId);
		
		//删除被操作者权限
		userEnterprisePermissionGroupRepository.deleteByUserIdAndEnterpriseId(userId, enterpriseId);
		
		//新增超级管理员权限
		UserEnterprisePermissionGroup uepg = new UserEnterprisePermissionGroup();
		uepg.setUserId(userId);
		uepg.setEnterpriseId(enterpriseId);
		uepg.setPermissionGroupsDescription(PermissionGroup.parseToString(new ArrayList<PermissionGroup>(){
			{
				add(PermissionGroup.superManagerPermissionGroup());
			}
		}));
		uepg.setManagerTime(new Date());
		userEnterprisePermissionGroupRepository.save(uepg);
		
		Date date = new Date();
		//告知用户权限变更(发送站内信、push、短信)
		String operatorEnterpriseRemarks = userEnterpriseDepartmentPositionRepository.findEnterpriseRemarks(operatorId, enterpriseId);
		String enterpriseName = enterpriseRepository.findNameById(enterpriseId);
		String text = operatorEnterpriseRemarks + "已将" + enterpriseName + "移交给您";
		sendInMail(operatorId, userId, text, date);//发送站内信
		sendPush(operatorId, userRepository.findUsernameById(userId), text, date);//发送push
		sendShortMail(operatorId, userId, text, date);//发送短信
		
		//记录权限变更操作
		String userEnterpriseRemarks = userEnterpriseDepartmentPositionRepository.findEnterpriseRemarks(userId, enterpriseId);
		ManagerUpdateLog mul = new ManagerUpdateLog();
		mul.setLog("主管理员" + operatorEnterpriseRemarks + "将主管理员权限移交给" + userEnterpriseRemarks);
		mul.setEnterpriseId(enterpriseId);
		mul.setDate(date);
		managerUpdateLogRepository.save(mul);
		
		return MapAsReturn.setStatusSuccess(null, null);
	}
	
	/**
	 * 创建管理员权限变更的消息
	 * @param operatorId 操作者id
	 * @param userId 被操作者id
	 * @param enterpriseId 公司id
	 * @param oldUepg 旧管理权限
	 * @param newUepg 新管理权限
	 * @return
	 */
	private String getTextAboutManagerUpdate(String operatorId, String userId, String enterpriseId, UserEnterprisePermissionGroup oldUepg, UserEnterprisePermissionGroup newUepg){
		String operatorEnterpriseRemarks = userEnterpriseDepartmentPositionRepository.findEnterpriseRemarks(operatorId, enterpriseId);
		String enterpriseName = enterpriseRepository.findNameById(enterpriseId);
		
		List<String> oldOpenNameAndTileList = oldUepg.getOpenNameAndTile();
		List<String> newOpenNameAndTileList = newUepg.getOpenNameAndTile();
		
		String text = null;
		if(oldOpenNameAndTileList.size() == 0){
			if(newOpenNameAndTileList.size() > 0){
				text = "您在" + enterpriseName + "已被管理员" + operatorEnterpriseRemarks + "任命为公司管理员。\r\n管理范围:";
				for(String element : newOpenNameAndTileList){
					text += element;
				}
			}
		}else{
			if(newOpenNameAndTileList.size() == 0){
				 text = "您在" + enterpriseName + "已被管理员" + operatorEnterpriseRemarks + "取消了管理员身份。";
			}else{
				text = "您在" + enterpriseName + "已被管理员" + operatorEnterpriseRemarks + "更改了管理权限。\r\n新的管理范围:";
				for(String element : newOpenNameAndTileList){
					text += element;
				}
			}
		}
		
		return text;
	}
	
	/**
	 * 发送与管理员权限变更有关的站内信
	 * @param senderId 发送者id
	 * @param receiverId 接受者id
	 * @param text 消息内容
	 * @param date 创建时间
	 * @return
	 */
	private Message sendInMail(String senderId, String receiverId, String text, Date date){
		Message message = new Message();
		message.setCreateId(senderId);
		message.setUserid(receiverId);
		message.setMessage(text);
		message.setTitle("变更消息");
		message.setSendWay(2);
		message.setMesType(5);
		message.setState(null);
		message.setIsRead(0);
		message.setDetailId(null);
		message.setCreatetime(date);
		return messageRepository.save(message);
	}
	
	/**
	 * 发送与管理员权限变更有关的短信,并保存发送短信记录
	 * @param senderId 发送者id
	 * @param receiverId 接受者id
	 * @param text 消息内容
	 * @param date 创建时间
	 * @return
	 */
	private Message sendShortMail(String senderId, String receiverId, String text, Date date){
		String receiverUsername = userRepository.findUsernameById(receiverId);
		//发送短信
		try{
			SendCode.sendMessage(receiverUsername, text);
		}catch(Exception e){
			logger.error("发送与管理员权限变更有关的短信时失败。");
		}
		
		//保存发送短信记录
		Message message = new Message();
		message.setCreateId(senderId);//设置创建者id为邀请者id
		message.setUserid(receiverUsername);//设置接受者id为被邀请者username
		message.setMessage(text);//设置消息内容
		message.setTitle("短信");//设置标题
		message.setSendWay(1);//设置发送方式为"短信"
		message.setMesType(5);//设置消息类型为"系统消息"
		message.setState(null);//设置消息状态为null
		message.setIsRead(null);//设置读状态为null
		message.setDetailId(null);//设置该消息所关联的邀请记录表中的记录
		message.setCreatetime(date);//设置创建时间
		return messageRepository.save(message);//保存消息记录
	}

	/**
	 * 发送与管理员权限变更有关的push
	 * @param senderId 发送者id
	 * @param receiverUsername 接受者手机号
	 * @param text 短信内容
	 * @param date 创建时间
	 * @return
	 */
	private void sendPush(String senderId, String receiverUsername, String text, Date date){
		JPushRestAPI jPushRestAPI = new JPushRestAPI();
		List<PushSwitch> list = pushSwitchRepository.findAll();
		PushSwitch pushSwitch  = list.get(0);
		if (pushSwitch.getIsSwitch() == 0) {
			jPushRestAPI.setApns_production(false);
		}
		jPushRestAPI.SendPush(text, null, null, "Default", jPushRestAPI.jsonDataByOneAlias(receiverUsername));
	}
	
	/**
	 * 保存用户权限变更记录
	 * @param operatorId 操作者id
	 * @param userId 被操作者id
	 * @param enterpriseId 公司id
	 * @param oldUepg 旧管理权限
	 * @param newUepg 新管理权限
	 * @param date 时间
	 */
	private void saveManagerUpdateLog(String operatorId, String userId, String enterpriseId, UserEnterprisePermissionGroup oldUepg, UserEnterprisePermissionGroup newUepg, Date date){
		//记录权限变更操作
		String operatorEnterpriseRemarks = userEnterpriseDepartmentPositionRepository.findEnterpriseRemarks(operatorId, enterpriseId);
		String userEnterpriseRemarks = userEnterpriseDepartmentPositionRepository.findEnterpriseRemarks(userId, enterpriseId);
		
		List<String> oldOpenNameAndTileList = oldUepg.getOpenNameAndTile();
		List<String> newOpenNameAndTileList = newUepg.getOpenNameAndTile();
		
		if(oldOpenNameAndTileList.size() == 0){
			if(newOpenNameAndTileList.size() > 0){
				String text = "主管理员" + operatorEnterpriseRemarks + "给" + userEnterpriseRemarks + "设置";
				for(String element : newOpenNameAndTileList){
					text += element;
				}
				ManagerUpdateLog mul = new ManagerUpdateLog();
				mul.setLog(text);
				mul.setEnterpriseId(enterpriseId);
				mul.setDate(date);
				managerUpdateLogRepository.save(mul);
			}
		}else{
			if(newOpenNameAndTileList.size() == 0){
				ManagerUpdateLog mul = new ManagerUpdateLog();
				mul.setLog("主管理员" + operatorEnterpriseRemarks + "将管理员" + userEnterpriseRemarks + "的身份撤销");
				mul.setEnterpriseId(enterpriseId);
				mul.setDate(date);
				managerUpdateLogRepository.save(mul);
			}else{
				ManagerUpdateLog mul = new ManagerUpdateLog();
				String text = "主管理员" + operatorEnterpriseRemarks + "将管理员的";
				for(String element : oldOpenNameAndTileList){
					text += element;
				}
				text += "变更为";
				for(String element : newOpenNameAndTileList){
					text += element;
				}
				mul.setLog(text);
				mul.setEnterpriseId(enterpriseId);
				mul.setDate(date);
				managerUpdateLogRepository.save(mul);
			}
		}
	}
	
}
